/*
 *  WilEventUtils.cpp
 *  Wilson
 *
 *  Created by Sebastian Orfino on 9/6/11.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */
#include "VCPlugInHeaders.h"

//stl includes
#include <string>
#include <map>
#include <fstream>
#include <boost/algorithm/string.hpp>

//project includes
#include "csxs_facade.h"
#include "evento_csxs_base.h"
#include "PlugPlugSDK.h"
#include "handler_functor.h"



#include "WilID.h"

using namespace wilson;

namespace wilson {
	
	namespace conversaciones {
		

		iniciador preparar_nueva(const conversacion_ptr& c)
		{
			static boost::circular_buffer<conversacion_ptr> conversaciones_(MAX_CONVERSACIONES);
			
			conversaciones_.push_back(c);
			return iniciador(conversaciones_.back());
		}
		
	}

	namespace extensiones {
		
		void activar(const char * ext_id)
		{
			PlugPlugErrorCode result = csxs::sdk::LoadExtension(ext_id);
			ASSERT_MSG(result == kEventErrorCode_Success,"no se pudo cargar la extension");
		}
	}
	
	namespace detail {

	/** Adapta los callbacks de CSXS a los functors de handler_functor
	 @param context Aqui siempre va a venir un puntero al objeto que implementa operator(handler_function_t)*/
		void fn_adapter(const csxs::event::Event * const eventParam, void* const context)
		{
			//T * t = (T*) context;
			if (!context) return;
			wilson::handler_functor * t = (wilson::handler_functor *) context;
			(*t)(eventParam);
		}
	}
	
	namespace {
	
		void escapar_chars(std::string& data)
		{
			using boost::algorithm::replace_all;
			replace_all(data, "&",  "&amp;");
			replace_all(data, "\"", "&quot;");
			replace_all(data, "\'", "&apos;");
			replace_all(data, "<",  "&lt;");
			replace_all(data, ">",  "&gt;");
			
			
		}
		
	}
	
		
	csxs::event::EventErrorCode olvidar(const char *evt, handler_functor * functor_ptr) 
	{
		//OJO: calculo que para csxs todos los fn_adapter van a ser iguales y es probable que al remover un (evt,handler)
		//en realidad me remueva todos los handler suscriptos a ese evt.
		return csxs::sdk::RemoveEventListener(evt,wilson::detail::fn_adapter,functor_ptr);
	}
	
	csxs::event::EventErrorCode despachar(const eventos::evento_csxs_base& evt)
	{			
		using namespace std;
		/** Que es esto ? bueno, es una recontraguarda de seguridad por si despacho muchos eventos. Te explico:
		 csxs::event::Event toma como payload un char *. Bien, el char* viene de evento_csxs_base::payload().c_str() y cuando el evento se
		 va de contexto se destruye el string y el char* que me devolvio c_str() apunta a mierda. Entonces preciso una forma de que ese
		 string siga vivo por un tiempo que no esta determinado en la documentacion. Que hago yo? bueno, mantengo en esta coleccion 5 strings
		 vivos que se van pisando (es circular) y "de alguna manera" estoy seguro que para cuando se destruya el 5to string su char* ya se uso en 
		 csxs::sdk::DispatchEvent() y no voy a tener problema. Cocinada ? puede ser.. */
		static boost::circular_buffer<std::string> buffer_payloads_(25); //el 5 es una idea aproximada..
		
		std::string data(evt.payload());
		escapar_chars(data);
		buffer_payloads_.push_back(data);
		
		csxs::event::Event event = { evt.ID(), evt.scope(), "ISDN", kWilNombreExtension, buffer_payloads_.back().c_str() };
		
		
		/*ofstream file("mi_csxsevent_data.xml", ios::trunc);
		file << event.data;
		file.close();
		*/
		csxs::event::EventErrorCode result = csxs::sdk::DispatchEvent(&event);
		
		return result;
	}
	
	csxs::event::EventErrorCode escuchar(const char *evt, handler_functor * functor_ptr) 
	{
		return csxs::sdk::AddEventListener(evt,wilson::detail::fn_adapter,functor_ptr);
	}
	
	
	
}







												   

